using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using SQLRunnerLib.Project;
using SQLServices.RunnableItems;

namespace SQLRunnerLib.RunnableItems
{
    /// <summary>
    /// It stores and manages all the scripts that are saved in a SQLRunner. It helps to
    /// maintain an index of all the files added to the project and can be used to add and
    /// modify items.
    /// </summary>
    public class ProjectManager
    {
        private ItemPath _projectRoot;
        private readonly Dictionary<string, IProjectItem> _indexItems;
        private readonly Dictionary<string, ProjectFolder> _rootFolders;

        public ProjectManager(string rootPath)
        {
            _projectRoot = new ItemPath(rootPath, string.Empty);
            _indexItems = new Dictionary<string, IProjectItem>();
            _rootFolders = new Dictionary<string, ProjectFolder>();
        }

        /// <summary>
        /// Indicates if a IProjectItem exists in the collection
        /// </summary>
        /// <param name="fullName"></param>
        /// <returns></returns>
        public bool Contains(string fullName)
        {
            return _indexItems.ContainsKey(fullName);
        }

        public IProjectItem GetProjectItem(string fullName)
        {
            return Contains(fullName) ? _indexItems[fullName] : null;
        }


        /// <summary>
        /// If folder is not included but any parent does, then this method
        /// finds the closest parent
        /// </summary>
        /// <param name="directory"></param>
        /// <returns></returns>
        public ProjectFolder FindParentFolder(DirectoryInfo directory)
        {
            if (directory.Parent == null) return null;
            if (Contains(directory.Parent.FullName)) return _indexItems[directory.Parent.FullName] as ProjectFolder;
            return FindParentFolder(directory.Parent);
        }

        /// <summary>
        /// Adds a new folder to the project, includes all files and subfolders
        /// </summary>
        /// <param name="directory"></param>
        /// <param name="root"></param>
        /// <returns></returns>
        public ProjectFolder AddFolder(DirectoryInfo directory, ProjectFolder root)
        {
            ProjectFolder tmpFolder = null;
            if (Contains(directory.FullName)) return null;
            if (root == null)
            {
                root = new ProjectFolder(
                    directory.FullName,
                    null,
                    false,
                    new ItemPath(directory.Root.FullName, directory.FullName));

                _indexItems.Add(root.Path.FullPath, root);
                _rootFolders.Add(root.Path.FullPath, root);
            }
            else
            {
                tmpFolder = new ProjectFolder(
                    directory.Name,
                    root,
                    root.Ignore,
                    new ItemPath(root.Path.FullPath, directory.FullName));
                
                root.Children.Add(tmpFolder);
                _indexItems.Add(tmpFolder.Path.FullPath, tmpFolder);
            }
            
            foreach (DirectoryInfo subDir in directory.GetDirectories())
            {
                AddFolder(subDir, root);                
            }

            foreach (FileInfo file in directory.GetFiles())
            {
                ProjectScript script = new ProjectScript(
                    file.Name,
                    tmpFolder ?? root,
                    root.Ignore,
                    new ItemPath(root.Path.FullPath, file.FullName));
                if( tmpFolder == null)
                {
                    root.Children.Add(script);
                }
                else
                {
                    tmpFolder.Children.Add(script);
                }
                _indexItems.Add(script.Path.FullPath, script);
            }

            return tmpFolder ?? root;
        }

        /// <summary>
        /// List of root project folders
        /// </summary>
        public Dictionary<string, ProjectFolder>.ValueCollection RootFolders
        {
            get { return _rootFolders.Values; }
        }
    }
}
